/** @file    SystemProfiler.cpp
 *  @author  Alessandro Polo
 *  @version $Id: SystemProfiler.cpp 2833 2010-08-02 23:12:57Z alex $
 *  @brief
 * File containing methods for the wosh::SystemProfiler class.
 * The header for this class can be found in SystemProfiler.h, check that file
 * for class description.
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

 #include <core/SystemProfiler.h>
 #include <core/ObjectAllocator.h>
 #include <core/Method.h>
 #include <core/Property.h>
 #include <core/BusConnector.h>
 #include <core/PropertiesProvider.h>
 #include <core/Object.h>
 #include <core/Bundle.h>
 #include <core/Table.h>
 #include <core/DataModels.h>
 #include <core/Utilities.h>
 #include <typeinfo> // dynamic_cast exception
 #include <stdio.h> // sprintf


using namespace std;
namespace wosh {

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

 WOSH_REGISTER(wosh::DeprecatedFunctionInfo, "wosh::ISerializable", 1.01, _static_DeprecatedFunctionInfo)

DeprecatedFunctionInfo::DeprecatedFunctionInfo( const char * oldFunctionName, const char * newFunctionName,
												void* calledFrom, const char * filename, unsigned int file_line )
	: OldFunctionName(oldFunctionName), NewFunctionName(newFunctionName),
		CalledFrom(calledFrom), FileName(filename), FileLine(file_line) {
 }

DeprecatedFunctionInfo& DeprecatedFunctionInfo::operator=( const DeprecatedFunctionInfo& m ) {
	if (this == &m) return *this; // same object?
	this->OldFunctionName = m.OldFunctionName;
	this->NewFunctionName = m.NewFunctionName;
	this->CalledFrom = m.CalledFrom;
	this->FileName = m.FileName;
	this->FileLine = m.FileLine;
	return *this;
 }

bool DeprecatedFunctionInfo::operator==(const DeprecatedFunctionInfo &other) const {
	if ( this->OldFunctionName != other.OldFunctionName ) return false;
	if ( this->NewFunctionName != other.NewFunctionName ) return false;
	if ( this->CalledFrom != other.CalledFrom ) return false;
	if ( this->FileName != other.FileName ) return false;
	if ( this->FileLine != other.FileLine ) return false;
	return true;
 }
 
DataFieldCollector<DeprecatedFunctionInfo>* DeprecatedFunctionInfo::getDataFields() {
	DataFieldCollector<DeprecatedFunctionInfo>* fields = new DataFieldCollector<DeprecatedFunctionInfo>();
	fields->add<const std::string&, Variant>(&DeprecatedFunctionInfo::getOldFunctionName, "OldFunctionName", 0);
	fields->add<const std::string&, Variant>(&DeprecatedFunctionInfo::getNewFunctionName, "NewFunctionName", 1);
	fields->add<const std::string&, Variant>(&DeprecatedFunctionInfo::getFileName, "FileName", 2);
	fields->add<int, Variant>(&DeprecatedFunctionInfo::getFileLine, "FileLine", 3);
	return fields;
 }

std::string DeprecatedFunctionInfo::toString() const {
	return Utilities::format("%s[%s=>%s]", getClassNameOnlyOf(getClassName()), this->OldFunctionName.c_str(), this->NewFunctionName.c_str() );
 }

bool DeprecatedFunctionInfo::updateHash( DataHashContext* hash_context ) const {
	if ( hash_context == NULL ) return false;
	bool ret = true;
	ret = hash_context->update( this->OldFunctionName ) & ret;
	ret = hash_context->update( this->NewFunctionName ) & ret;
	//ret = hash_context->update( this->CalledFrom ) & ret;
	ret = hash_context->update( this->FileName ) & ret;
	ret = hash_context->update( this->FileLine ) & ret;
	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

 WOSH_REGISTER_INTERFACE(wosh::ProfileInfo, "wosh::ISerializable", 1.01, _static_ProfileInfo)

std::string ProfileInfo::getPtrAsString() const {
	if ( this->ptr == NULL ) return "";
	return Utilities::format("%p", this->ptr);
 }

std::string ProfileInfo::getParentPtrAsString() const {
	if ( this->parentPtr == NULL ) return "";
	return Utilities::format("%p", this->parentPtr);
 }

ProfileInfo& ProfileInfo::operator=( const ProfileInfo& m ) {
	if (this == &m) return *this; // same object?
	this->name = m.name;
	this->accessCount = m.accessCount;
	this->concurrentCount = m.concurrentCount;
	this->parentPtr = m.parentPtr;
	this->parentClass = m.parentClass;
	this->parentName = m.parentName;
	return *this;
 }

bool ProfileInfo::operator==(const ProfileInfo &other) const {
	if ( this->name != other.name ) return false;
	if ( this->accessCount != other.accessCount ) return false;
	if ( this->concurrentCount != other.concurrentCount ) return false;
	if ( this->parentPtr != other.parentPtr ) return false;
	if ( this->parentClass != other.parentClass ) return false;
	if ( this->parentName != other.parentName ) return false;
	return true;
 }

DataFieldCollector<ProfileInfo>* ProfileInfo::getDataFields() {
	DataFieldCollector<ProfileInfo>* fields = new DataFieldCollector<ProfileInfo>();
	fields->add<std::string, Variant>(&ProfileInfo::getPtrAsString, "Address", 0);
	fields->add<const std::string&, Variant>(&ProfileInfo::getName, "Name", 1);
	fields->add<int64, Variant>(&ProfileInfo::getAccessCount, "AccessCount", 2);
	fields->add<int, Variant>(&ProfileInfo::getConcurrentCount, "ConcurrentCount", 3);
	fields->add<const std::string&, Variant>(&ProfileInfo::getParentClass, "ParentClass", 4);
	fields->add<const std::string&, Variant>(&ProfileInfo::getParentName, "ParentName", 5);
	fields->add<std::string, Variant>(&ProfileInfo::getParentPtrAsString, "ParentPtr", 6);
	return fields;
 }

std::string ProfileInfo::toString() const {
	return Utilities::format("%s[%s,%s]", getClassNameOnlyOf(getClassName()), this->name.c_str(), this->accessCount );
 }

bool ProfileInfo::updateHash( DataHashContext* hash_context ) const {
	if ( hash_context == NULL ) return false;
	bool ret = true;
	ret = hash_context->update( this->name ) & ret;
	ret = hash_context->update( this->accessCount ) & ret;
	ret = hash_context->update( this->concurrentCount ) & ret;
	ret = hash_context->update( this->parentClass ) & ret;
	ret = hash_context->update( this->parentName ) & ret;
	return ret;
 }

void ProfileInfo::setParentInfo( const IReflection* parent ) {
	this->parentPtr = static_cast<const void*>(parent);
	if ( parent != NULL ) {
		this->parentClass = parent->getClassName();
		const Object* parent_obj = dynamic_cast<const Object*>(parent);
		if ( parent_obj != NULL ) {
			this->parentName = parent_obj->getName(); // entity ?
		 }
		else {
			const Bundle* parent_bundle = dynamic_cast<const Bundle*>(parent);
			if ( parent_bundle != NULL )
				this->parentName = parent_bundle->getName();
		}
	 }
	else
		this->parentClass = "UNKNOWN";
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

 WOSH_REGISTER(wosh::ProfileInfoMethod, "wosh::ProfileInfo", 1.01, _static_ProfileInfoMethod)

void ProfileInfoMethod::setMethod( const Method* method, const MethodRunner* parent ) {
	if ( method == NULL ) return;
	this->mux.lockForWrite();
	this->methodClass = method->getClassName();
	this->name = method->getName();
	this->linkedFunction = method->isLinkedFunction();
	this->linkedParent = method->isLinkedParent();
	try {
		const IReflection* ip = dynamic_cast<const IReflection*>(parent);
		setParentInfo( ip );
	 }
#ifdef _MSC_VER
	catch(__non_rtti_object &) {
		setParentInfo(NULL);
	 }
#endif
	catch(std::bad_cast) {
		setParentInfo(NULL);
	 }
	this->mux.unLock();
 }

void ProfileInfoMethod::enter( short ) {
	this->mux.lockForWrite();
	++this->accessCount;
	++this->concurrentCount;
	this->mux.unLock();
 }

DataFieldCollector<ProfileInfoMethod>* ProfileInfoMethod::getDataFields() {
	DataFieldCollector<ProfileInfoMethod>* fields = new DataFieldCollector<ProfileInfoMethod>();
	fields->add<std::string, Variant>(&ProfileInfoMethod::getPtrAsString, "Address", 0);
	fields->add<const std::string&, Variant>(&ProfileInfoMethod::getName, "Name", 1);
	fields->add<const std::string&, Variant>(&ProfileInfoMethod::getMethodClass, "Class", 2);
	fields->add<int64, Variant>(&ProfileInfoMethod::getAccessCount, "Calls", 3);
	fields->add<int, Variant>(&ProfileInfoMethod::getConcurrentCount, "ConcurrentCalls", 4);
	fields->add<const std::string&, Variant>(&ProfileInfoMethod::getParentClass, "ParentClass", 5);
	fields->add<const std::string&, Variant>(&ProfileInfoMethod::getParentName, "ParentName", 6);
	fields->add<std::string, Variant>(&ProfileInfoMethod::getParentPtrAsString, "ParentPtr", 7);
	fields->add<bool, Variant>(&ProfileInfoMethod::isLinkedFunction, "LF", 8);
	fields->add<bool, Variant>(&ProfileInfoMethod::isLinkedParent, "LP", 9);
	return fields;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

 WOSH_REGISTER(wosh::ProfileInfoProperty, "wosh::ProfileInfo", 1.01, _static_ProfileInfoProperty)

void ProfileInfoProperty::setProperty( const Property* prop, const IPropertiesProviderListener* parent ) {
	if ( prop == NULL ) return;
	this->mux.lockForWrite();
	this->name = prop->getKey();
	try {
		const IReflection* ip = dynamic_cast<const IReflection*>(parent);
		setParentInfo( ip );
	 }
#ifdef _MSC_VER
	catch(__non_rtti_object &) {
		setParentInfo(NULL);
	 }
#endif
	catch(bad_cast) {
		setParentInfo(NULL);
	 }
	this->mux.unLock();
 }

void ProfileInfoProperty::enter( short read_or_write ) {
	this->mux.lockForWrite();
	++this->accessCount;
	++this->concurrentCount;
	if ( read_or_write == 0 )
		++this->readCount;
	else
		++this->writeCount;
	this->mux.unLock();
 }

DataFieldCollector<ProfileInfoProperty>* ProfileInfoProperty::getDataFields() {
	DataFieldCollector<ProfileInfoProperty>* fields = new DataFieldCollector<ProfileInfoProperty>();
	fields->add<std::string, Variant>(&ProfileInfoProperty::getPtrAsString, "Address", 0);
	fields->add<const std::string&, Variant>(&ProfileInfoProperty::getName, "Name", 1);
	fields->add<int64, Variant>(&ProfileInfoProperty::getReadCount, "#Reads", 2);
	fields->add<int64, Variant>(&ProfileInfoProperty::getWriteCount, "#Writes", 3);
	fields->add<int, Variant>(&ProfileInfoProperty::getConcurrentCount, "ConcurrentCalls", 4);
	fields->add<const std::string&, Variant>(&ProfileInfoProperty::getParentClass, "ParentClass", 5);
	fields->add<const std::string&, Variant>(&ProfileInfoProperty::getParentName, "ParentName", 6);
	fields->add<std::string, Variant>(&ProfileInfoProperty::getParentPtrAsString, "ParentPtr", 7);
	return fields;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

 WOSH_REGISTER(wosh::ProfileInfoConnector, "wosh::ProfileInfo", 1.01, _static_ProfileInfoConnector)

void ProfileInfoConnector::setConnector( const BusConnector* conn, const IBusListener* parent ) {
	if ( conn == NULL ) return;
	this->mux.lockForWrite();
	this->name = conn->getBusName();
	try {
		const IReflection* ip = dynamic_cast<const IReflection*>(parent);
		setParentInfo( ip );
	 }
#ifdef _MSC_VER
	catch(__non_rtti_object &) {
		setParentInfo(NULL);
	 }
#endif
	catch(bad_cast) {
		setParentInfo(NULL);
	 }
	this->mux.unLock();
 }

void ProfileInfoConnector::enter( short input_or_output ) {
	this->mux.lockForWrite();
	++this->accessCount;
	++this->concurrentCount;
	if ( input_or_output == 0 )
		++this->inputCount;
	else
		++this->outputCount;
	this->mux.unLock();
 }

DataFieldCollector<ProfileInfoConnector>* ProfileInfoConnector::getDataFields() {
	DataFieldCollector<ProfileInfoConnector>* fields = new DataFieldCollector<ProfileInfoConnector>();
	fields->add<std::string, Variant>(&ProfileInfoConnector::getPtrAsString, "Address", 0);
	fields->add<const std::string&, Variant>(&ProfileInfoConnector::getName, "Name", 1);
	fields->add<int64, Variant>(&ProfileInfoConnector::getInputCount, "#Inputs", 2);
	fields->add<int64, Variant>(&ProfileInfoConnector::getOutputCount, "#Outputs", 3);
	fields->add<int, Variant>(&ProfileInfoConnector::getConcurrentCount, "ConcurrentCalls", 4);
	fields->add<const std::string&, Variant>(&ProfileInfoConnector::getParentClass, "ParentClass", 5);
	fields->add<const std::string&, Variant>(&ProfileInfoConnector::getParentName, "ParentName", 6);
	fields->add<std::string, Variant>(&ProfileInfoConnector::getParentPtrAsString, "ParentPtr", 7);
	return fields;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef _ENABLE_PROFILING
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

 // Meyer singleton! static reference is allocated on first user
 // not thread safe
extern "C" {
	SystemProfiler& SystemProfiler::getInstance() {
		static SystemProfiler ans;
		return ans;
	}
}

SystemProfiler::~SystemProfiler() { 
	// DO NOT DELETE KEYS! they are sort of 'lost pointers' from the beginning
	// accessed while initialization, then ONLY for pointer-comparison
	this->profilesMethods.clear();
	this->profilesProperties.clear();
	this->profilesConnectors.clear();

	// this->deprecatedList holds (non-pointer) objects so it will be automatically free by stl/compiler
}

void SystemProfiler::deprecated( const char * OldFunctionName, const char * NewFunctionName,
								 void* CalledFrom, const char * filename, unsigned int file_line )
 {
	DeprecatedFunctionInfo info(OldFunctionName, NewFunctionName, CalledFrom, filename, file_line);
	this->deprecatedList.transactionBeginWrite();
	this->deprecatedList.push_back(info, true);
	this->deprecatedList.transactionEnd();
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// specialization for Method

ProfileInfoMethod* SystemProfiler::getCreateProfile( const Method* object, const MethodRunner* owner ) {
	if ( object == NULL ) return NULL;
	ProfileInfoMethod* info = this->profilesMethods.find(object);
	// avoid concurrent registrations/updates
	this->profilesMethods.transactionBeginWrite();
	if ( info == NULL ) {
		info = new ProfileInfoMethod();
		info->setMethod(object, owner);
	}
	else if ( info->parentPtr != owner )
		info->setMethod(object, owner);
	this->profilesMethods.set(object, info);
	this->profilesMethods.transactionEnd();
	return info;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// specialization for Property

ProfileInfoProperty* SystemProfiler::getCreateProfile( const Property* object, const IPropertiesProviderListener* owner ) {
	if ( object == NULL ) return NULL;
	ProfileInfoProperty* info = this->profilesProperties.find(object);
	// avoid concurrent registrations/updates
	this->profilesProperties.transactionBeginWrite();
	if ( info == NULL ) {
		info = new ProfileInfoProperty();
		info->setProperty(object, owner);
	 }
	else if ( info->parentPtr != owner )
		info->setProperty(object, owner);
	this->profilesProperties.set(object, info);
	this->profilesProperties.transactionEnd();
	return info;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// specialization for BusConnector

ProfileInfoConnector* SystemProfiler::getCreateProfile( const BusConnector* object, const IBusListener* owner ) {
	if ( object == NULL ) return NULL;
	ProfileInfoConnector* info = this->profilesConnectors.find(object);
	// avoid concurrent registrations/updates
	this->profilesConnectors.transactionBeginWrite();
	if ( info == NULL ) {
		info = new ProfileInfoConnector();
		info->setConnector(object, owner);
	 }
	else if ( info->parentPtr != owner )
		info->setConnector(object, owner);
	this->profilesConnectors.set(object, info);
	this->profilesConnectors.transactionEnd();
	return info;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

Table* SystemProfiler::getDeprecatedTable() const {
	this->deprecatedList.transactionBeginRead(); // avoid new insertion
	Table* tbl = new Table( this->deprecatedList.size(), 5, true );
	tbl->setTableName("Deprecated List");
	tbl->setHeaderHorizontal("(Old) FunctionName", 0);
	tbl->setHeaderHorizontal("New FunctionName", 1);
	tbl->setHeaderHorizontal("Called From", 2);
	tbl->setHeaderHorizontal("FileName", 3);
	tbl->setHeaderHorizontal("FileLine", 4);
	unsigned int iRow = 0;
	char addressBuffer[16];
	tDeprecatedFunctionInfoList::ConstIterator it;
	const tDeprecatedFunctionInfoList::ConstIterator it_end = this->deprecatedList.end();
	for ( it=this->deprecatedList.begin(); it!=it_end; ++it, ++iRow ) {
		sprintf(addressBuffer, "%p", (*it).CalledFrom);
		tbl->set<Variant>( (*it).OldFunctionName, iRow, 0);
		tbl->set<Variant>( (*it).NewFunctionName, iRow, 1);
		tbl->set<Variant>( addressBuffer, iRow, 2);
		tbl->set<Variant>( (*it).FileName, iRow, 3);
		tbl->set<Variant>( (long)(*it).FileLine, iRow, 4);
	 }
	this->deprecatedList.transactionEnd();
	return tbl;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

template <class CONTAINER>
unsigned int getAccessedCount( const CONTAINER& list, int64 access_threshold ) {
	unsigned int count = 0;
	typename CONTAINER::ConstIterator it;
	const typename CONTAINER::ConstIterator it_end = list.end();
	for ( it=list.begin(); it!=it_end; ++it ) {
		if ( it->second == NULL ) continue;
		it->second->mux.lockForRead();
		if ( it->second->accessCount >= access_threshold )
			++count;
		it->second->mux.unLock();
	}
	return count;
}

// THIS IS AN HUGE LIST!!!!!
// non blocking against execution, BLOCKING against NEW INSERTIONs
Table* SystemProfiler::getProfilesMethodsTable( int64 access_threshold ) const {
	this->profilesMethods.transactionBeginRead(); // avoid new insertion
	unsigned int count = this->profilesMethods.size();
	if ( access_threshold != 0 )
		count = getAccessedCount<tVoidPtrProfileInfoMethodMap>(this->profilesMethods, access_threshold);
	Table* tbl = new Table( count, 9, true );
	tbl->setTableName( Utilities::format("Methods Profiling data [AC>%ld]", access_threshold) );
	tbl->setHeaderHorizontal("Address", 0);
	tbl->setHeaderHorizontal("Name", 1);
	tbl->setHeaderHorizontal("Class", 2);
	tbl->setHeaderHorizontal("LF", 3);
	tbl->setHeaderHorizontal("LP", 4);
	tbl->setHeaderHorizontal("ParentName", 5);
	tbl->setHeaderHorizontal("ParentClass", 6);
	tbl->setHeaderHorizontal("Calls", 7);
	tbl->setHeaderHorizontal("C-Calls", 8);
	unsigned int iRow = 0;
	char addressBuffer[16];
	tVoidPtrProfileInfoMethodMap::ConstIterator it;
	const tVoidPtrProfileInfoMethodMap::ConstIterator it_end = this->profilesMethods.end();
	for ( it=this->profilesMethods.begin(); it!=it_end; ++it ) {
		if ( it->second == NULL ) continue;
		sprintf(addressBuffer, "%p", it->first);
		it->second->mux.lockForRead();
		if ( access_threshold != 0 && it->second->accessCount < access_threshold ) {
			it->second->mux.unLock();
			continue;
		 }
		tbl->set<Variant>( addressBuffer, iRow, 0);
		tbl->set<Variant>( it->second->name, iRow, 1);
		tbl->set<Variant>( it->second->methodClass, iRow, 2);
		tbl->set<Variant>( it->second->linkedFunction, iRow, 3);
		tbl->set<Variant>( it->second->linkedParent, iRow, 4);
		tbl->set<Variant>( it->second->parentName, iRow, 5);
		tbl->set<Variant>( it->second->parentClass, iRow, 6);
		tbl->set<Variant>( it->second->accessCount, iRow, 7);
		tbl->set<Variant>( it->second->concurrentCount, iRow, 8);
		it->second->mux.unLock();
		++iRow;
	 }
	this->profilesMethods.transactionEnd();
	return tbl;
 }

// THIS IS AN HUGE LIST!!!!!
// non blocking against execution, BLOCKING against NEW INSERTIONs
Table* SystemProfiler::getProfilesPropertiesTable( int64 access_threshold ) const {
	this->profilesProperties.transactionBeginRead(); // avoid new insertion
	unsigned int count = this->profilesProperties.size();
	if ( access_threshold != 0 )
		count = getAccessedCount<tVoidPtrProfileInfoPropertyMap>(this->profilesProperties, access_threshold);
	Table* tbl = new Table( count, 6, true );
	tbl->setTableName( Utilities::format("Properties Profiling data [AC>%ld]", access_threshold) );
	tbl->setHeaderHorizontal("Address", 0);
	tbl->setHeaderHorizontal("Key", 1);
	tbl->setHeaderHorizontal("ParentName", 2);
	tbl->setHeaderHorizontal("ParentClass", 3);
	tbl->setHeaderHorizontal("#Reads", 4);
	tbl->setHeaderHorizontal("#Writes", 5);
	unsigned int iRow = 0;
	char addressBuffer[16];
	tVoidPtrProfileInfoPropertyMap::ConstIterator it;
	const tVoidPtrProfileInfoPropertyMap::ConstIterator it_end = this->profilesProperties.end();
	for ( it=this->profilesProperties.begin(); it!=it_end; ++it ) {
		if ( it->second == NULL ) continue;
		sprintf(addressBuffer, "%p", it->first);
		it->second->mux.lockForRead();
		if ( access_threshold != 0 && it->second->accessCount < access_threshold ) {
			it->second->mux.unLock();
			continue;
		 }
		tbl->set<Variant>( addressBuffer, iRow, 0);
		tbl->set<Variant>( it->second->name, iRow, 1);
		tbl->set<Variant>( it->second->parentName, iRow, 2);
		tbl->set<Variant>( it->second->parentClass, iRow, 3);
		tbl->set<Variant>( it->second->readCount, iRow, 4);
		tbl->set<Variant>( it->second->writeCount, iRow, 5);
		it->second->mux.unLock();
		++iRow;
	 }
	this->profilesProperties.transactionEnd();
	return tbl;
}

// THIS IS AN HUGE LIST!!!!!
// non blocking against execution, BLOCKING against NEW INSERTIONs
Table* SystemProfiler::getProfilesConnectorsTable( int64 access_threshold ) const {
	this->profilesConnectors.transactionBeginRead(); // avoid new insertion
	unsigned int count = this->profilesConnectors.size();
	if ( access_threshold != 0 )
		count = getAccessedCount<tVoidPtrProfileInfoConnectorMap>(this->profilesConnectors, access_threshold);
	Table* tbl = new Table( count, 6, true );
	tbl->setTableName( Utilities::format("BusConnector Profiling data [AC>%ld]", access_threshold) );
	tbl->setHeaderHorizontal("Address", 0);
	tbl->setHeaderHorizontal("BusName", 1);
	tbl->setHeaderHorizontal("ParentName", 2);
	tbl->setHeaderHorizontal("ParentClass", 3);
	tbl->setHeaderHorizontal("#Incoming", 4);
	tbl->setHeaderHorizontal("#Outgoing", 5);
	unsigned int iRow = 0;
	char addressBuffer[16];
	tVoidPtrProfileInfoConnectorMap::ConstIterator it;
	const tVoidPtrProfileInfoConnectorMap::ConstIterator it_end = this->profilesConnectors.end();
	for ( it=this->profilesConnectors.begin(); it!=it_end; ++it ) {
		if ( it->second == NULL ) continue;
		sprintf(addressBuffer, "%p", it->first);
		it->second->mux.lockForRead();
		if ( access_threshold != 0 && it->second->accessCount < access_threshold ) {
			it->second->mux.unLock();
			continue;
		 }
		tbl->set<Variant>( addressBuffer, iRow, 0);
		tbl->set<Variant>( it->second->name, iRow, 1);
		tbl->set<Variant>( it->second->parentName, iRow, 2);
		tbl->set<Variant>( it->second->parentClass, iRow, 3);
		tbl->set<Variant>( it->second->inputCount, iRow, 4);
		tbl->set<Variant>( it->second->outputCount, iRow, 5);
		it->second->mux.unLock();
		++iRow;
	 }
	this->profilesConnectors.transactionEnd();
	return tbl;
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

}; // namespace wosh
